#pragma once

#ifndef __MY_ROUTE__
#define __MY_ROUTE__

#include <iostream>
#include <string>
#include <vector>
#include "../mqcommon/message.pb.h"
#include "../mqcommon/helpper.hpp"

namespace NS_Route
{
    class Router
    {
    public:
        static bool isLegalRoutingKey(const std::string rouing_key)
        {
            for (auto &ch : rouing_key)
            {
                if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '.')
                    continue;

                return false;
            }

            return true;
        }

        static bool isLegalBindingKey(const std::string binding_key)
        {
            // 判断binding_key中是否含有非法字符
            for (auto &ch : binding_key)
            {
                if ((ch >= 'a' && ch <= 'z') 
                || (ch >= 'A' && ch <= 'Z') 
                || (ch >= '0' && ch <= '9') 
                || ch == '_' || ch == '.' 
                || ch == '*' || ch == '#')
                    continue;

                return false;
            }

            // 判断单词中是否含有* #
            std::vector<std::string> sub_words;
            NS_Helper::String::split(binding_key, ".", sub_words);
            for (auto &str : sub_words)
            {
                if (str.size() > 1 && (str.find("*") != std::string::npos || str.find("#") != std::string::npos))
                    return false;
            }

            // 判断 # 的两边是否有其他通配符
            for (int i = 1; i < sub_words.size(); i++)
            {
                if (sub_words[i] == "#")
                {
                    if (sub_words[i - 1] == "#" || sub_words[i - 1] == "*")
                        return false;
                }
                else if (sub_words[i] == "*" && sub_words[i - 1] == "#")
                    return false;
            }

            return true;
        }

        static bool isMatch(NS_Message::ExchangeType type, const std::string binding_key, const std::string routing_key)
        {
            if (!isLegalBindingKey(binding_key))
            {
                ELOG("binding_key不合法：%s", binding_key.c_str());
                return false;
            }

            if (!isLegalRoutingKey(routing_key))
            {
                ELOG("rouing_key不合法：%s", routing_key.c_str());
                return false;
            }

            if (type == NS_Message::ExchangeType::FANOUT)
                return true;
            else if (type == NS_Message::ExchangeType::DIRECT)
                return binding_key == routing_key;
            else if (type == NS_Message::ExchangeType::TOPIC)
            {
                std::vector<std::string> binding, routing;
                NS_Helper::String::split(binding_key, ".", binding);
                NS_Helper::String::split(routing_key, ".", routing);

                int m = binding.size(), n = routing.size();
                std::vector<std::vector<bool>> dp(m + 1, std::vector<bool>(n + 1));
                dp[0][0] = 1;
                for(int i = 1; i <= m; i++)
                {
                    if(binding[i - 1] == "#")
                    {
                        dp[i][0] = dp[i - 1][0];
                    }
                    else if(binding[i - 1] == "*")
                        dp[i][0] = false;
                    else
                    {
                        dp[i][0] = false;
                    }
                }

                for(int i = 1; i <= n; i++)
                {
                    dp[0][i] = false;
                }

                for(int i = 1; i <= m; i++)
                {
                    for(int j = 1; j <= n; j++)
                    {
                        if(binding[i - 1] == "#")
                        {
                            dp[i][j] = dp[i - 1][j - 1] | dp[i - 1][j] | dp[i][j - 1];
                        }
                        else if(binding[i - 1] == "*")
                            dp[i][j] = dp[i - 1][j - 1];
                        else
                        {
                            dp[i][j] = (binding[i - 1] == routing[j - 1]) & dp[i - 1][j - 1];
                        }
                        // std::cout << dp[i][j] << " ";
                    }
                    // std::cout << std::endl;
                }
                return dp[m][n];
            }
            else
            {
                ELOG("交换机类型不合法，%d", type);
                return false;
            }
        }
    };
}

#endif